package jmine.tec.proxy.chain;

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * Implementation of {@link InvocationHandler} that takes {@link ChainElement}s
 * and ultimately delegates the method execution the the given delegate object.
 * 
 * @author takeshi
 * 
 */
public final class ChainedInvocationHandler implements InvocationHandler, Serializable {

    private static final long serialVersionUID = 8611398429999078799L;

    private final ChainElement[] elements;

    private final Object delegate;

    /**
     * C'tor
     * 
     * @param delegate
     *            {@link Object}
     * @param elements
     *            the {@link ChainElement} that will intercept the method
     */
    public ChainedInvocationHandler(final Object delegate, final ChainElement... elements) {
        super();
        this.delegate = delegate;
        this.elements = elements;
    }

    /**
     * @param proxy
     *            {@link Object}
     * @param method
     *            {@link Method}
     * @param args
     *            {@link Object}
     * @throws Throwable
     *             e
     * @return {@link Object}
     */
    public Object invoke(final Object proxy, final Method method, final Object[] args)
            throws Throwable {
        InvocationChain chain =
                new DelegatingInvocationChain(this.delegate, this.elements, method, proxy, args);
        return chain.proceed();
    }

}
